import {
  Component, EventEmitter, HostBinding, Input, OnDestroy, OnInit,
  Output, TemplateRef, ViewChild
} from '@angular/core';
import { EventEditorService, DesignerEnvType, DesignerHostSettingService, DesignViewModelService, DomService, FormBasicService, SchemaService, FormSchemaEntityField, FormSchemaEntityField$Type } from '@farris/designer-services';
import { constants, ContainerOptions, DropResult, smoothDnD } from '@farris/smooth-dnd';
import { NotifyService } from '@farris/ui-notify';
import { TreeNode, TreeTableComponent } from '@farris/ui-treetable';
import { DgControl } from '../../../../../../utils/dg-control';


const SELECT_MOVE_COLUMN_MESSAGE = '请选择要移动显示的列。';

/**
 * 列表/树列表的列选择器，生成GridField/TreeGridField
 */
@Component({
  selector: 'app-grid-field-editor',
  templateUrl: './grid-field-editor.component.html',
  styleUrls: ['./grid-field-editor.component.css']
})
export class GridFieldEditorComponent implements OnInit, OnDestroy {
  @Output() closeModal = new EventEmitter<any>();
  @Output() submitModal = new EventEmitter<any>();
  @Input() value;  // datagrid控件 fields字段
  @Input() editorParams: any = {};
  @ViewChild('gridFieldFooter') modalFooter: TemplateRef<any>;
  modalConfig = {
    title: '列编辑器',
    width: 900,
    height: 500,
    showButtons: true
  };

  @ViewChild('tt') sourceTree: TreeTableComponent;
  idField = 'id';

  @HostBinding('class')
  cls = 'h-100 d-flex flex-column p-2 flex-fill';

  // 左侧选中的列
  get leftCheckeds() {
    if (this.sourceTree.selections) {
      return this.sourceTree.selections.map(n => {
        return n.data;
      });
    } else {
      return [];
    }
  }

  // 右侧显示列
  selectedColumns = [];

  // 右侧选中的列
  rightCheckeds: any = {};

  // 左侧树
  sourceColumnsTreeData: TreeNode[] = [];

  // 打平关联字段后的列数据
  plainColumns: TreeNode[] = [];

  // 列表是否需要列编辑器
  fieldEditable = false;

  /** 控件创建服务 */
  private controlCreatorService: any;

  /** 同一个实体，已经在其他列表中使用过的字段id */
  private fieldIdsInOhterGrids: string[] = [];

  constructor(
    private dgVMService: DesignViewModelService,
    private notifyService: NotifyService,
    private domService: DomService,
    private designerHost: DesignerHostSettingService,
    private formBasicService: FormBasicService,
    private schemaService: SchemaService,
    private eventEditorService: EventEditorService) {
    this.controlCreatorService = this.designerHost.designerHost.getService('ControlCreatorService');

  }

  ngOnInit(): void {
    if (!this.editorParams) {
      return;
    }
    this.sourceColumnsTreeData = this.dgVMService.getAllFields2TreeByVMId(this.editorParams['viewModelId']);

    this.fieldEditable = this.editorParams['fieldEditable'];
    this.getSelectedColumns();

    this.getFieldIdsInOtherForms();
  }



  ngOnDestroy() {
    if (this['sourceTreeContainer']) {
      this['sourceTreeContainer'].dispose();
    }
  }

  /**
   * 获取已选择的列
   */
  getSelectedColumns() {
    this.plainColumns = this.convertTreeNodes2PlainObject(this.sourceColumnsTreeData);
    if (!this.value || this.value.length === 0) {
      return [];
    }

    this.value.forEach(value => {
      if (value.binding && value.binding.field) {
        const element = this.plainColumns.find(el => el.data.id === value.binding.field);
        if (element) {
          if (element.data.$type === FormSchemaEntityField$Type.ComplexField) {
            this.selectedColumns.push(Object.assign({ isInValidBinding: true, inValidTip: '绑定字段已失效，请手动移除列' }, element.data));

          } else {
            this.selectedColumns.push(Object.assign({}, element.data));

          }
        } else {
          this.selectedColumns.push({
            id: value.binding.field,
            name: value.caption,
            bindingField: null,
            isInValidBinding: true,
            inValidTip: '绑定字段不存在，请手动移除列'
          });
        }

      }

    });


  }


  /**
   * 获取在其他列表中已使用的字段id，这些字段在当前列表中不允许再添加
   */
  private getFieldIdsInOtherForms() {
    this.fieldIdsInOhterGrids = [];
    const currentVM = this.domService.getViewModelById(this.editorParams.viewModelId);
    const currentCmp = this.domService.getComponentByVMId(this.editorParams.viewModelId);

    this.domService.viewmodels.forEach(vm => {

      // 绑定同一个实体，且都为卡片组件
      if (vm.id === this.editorParams.viewModelId || !vm.fields || !vm.fields.length || vm.bindTo !== currentVM.bindTo) {
        return;
      }
      const cmpNode = this.domService.getComponentByVMId(vm.id);
      if (currentCmp.componentType === cmpNode.componentType) {
        const fieldIds = vm.fields.map(f => f.id);
        this.fieldIdsInOhterGrids = this.fieldIdsInOhterGrids.concat(fieldIds);
      }

    });


  }

  isChecked(col: any, direction: string): boolean {
    if (direction === 'l') {
      return this.leftCheckeds[col['id']] !== undefined;
    } else {
      return this.rightCheckeds[col['id']] !== undefined;
    }
  }

  /**
   * 字段是否可勾选
   * 1、已选字段不可勾选
   * 2、主表的udt字段、关联字段不可勾选
   * @param col
   */
  canChecked(col) {
    if (col.type && col.type.fields && col.type.fields.length > 0) {
      return false;
    }
    if (this.fieldIdsInOhterGrids.includes(col['id'])) {
      return false;
    }
    if (this.selectedColumns.length === 0) {
      return true;
    }
    if (this.selectedColumns.findIndex(c => c['id'] === col['id']) === -1) {
      return true;
    }


  }



  hasCheckeds(side: string) {
    if (side === 'l') {
      return this.leftCheckeds.length > 0;
    } else {
      return Object.keys(this.rightCheckeds).length > 0;
    }
  }

  rightColumnChecked(col) {
    if (this.isChecked(col, 'r')) {
      this.rightCheckeds = {};
      return;
    } else {
      this.rightCheckeds = {};
      this.rightCheckeds[col['id']] = col;
    }
  }

  //#region 左右移动

  /** 右移 */
  moveToRight() {
    if (this.hasCheckeds('l')) {
      this.leftCheckeds.forEach(col => {
        if (this.selectedColumns.findIndex(selectedCo => selectedCo.id === col.id) === -1) {
          // this.selectedColumns.push(col);
          this.selectedColumns.push(Object.assign({}, col));
        }
      });
      this.clearSelections();
    } else {
      this.notifyService.warning('请选择要显示的列。');
    }
  }

  private clearSelections() {
    this.sourceTree.selectedRow = undefined;
    this.sourceTree.clearAll();
  }

  /**
   * 全部右移：主表的关联、udt字段不可右移
   */
  // bug fix
  moveAllToRight() {
    this.plainColumns.filter(col => {
      const data = col.data;
      if (data.type && data.type.fields && data.type.fields.length > 0) {
        return false;
      }
      if (this.fieldIdsInOhterGrids.includes(col.id)) {
        return false;
      }
      return this.selectedColumns.findIndex(selectedCo => selectedCo.id === col.id) === -1;
    }).forEach(col => {
      // this.selectedColumns.push(col.data);
      this.selectedColumns.push(Object.assign({}, col.data));
    });

    this.clearSelections();
  }

  /** 左移 */
  moveToLeft() {
    if (this.hasCheckeds('r')) {
      this.selectedColumns = this.selectedColumns.filter(v => {
        return Object.values(this.rightCheckeds).indexOf(v) === -1;
      });

      this.rightCheckeds = {};
    } else {
      this.notifyService.warning('请选择要取消显示的列。');
    }
  }

  /** 全部左移 */
  moveAllToLeft() {
    this.selectedColumns = [];

  }

  //#endregion

  //#region 上下移动显示列顺序

  _getSelectColumnInfo() {
    if (this.hasCheckeds('r')) {
      const cols = Object.values(this.rightCheckeds);
      const index = this.selectedColumns.findIndex(c => c === cols[0]);
      return {
        cols, index
      };
    }

    return null;
  }
  /** 置顶 */
  moveTop() {
    const obj = this._getSelectColumnInfo();
    if (obj) {
      this.selectedColumns.unshift(this.selectedColumns[obj.index]);
      this.selectedColumns.splice(obj.index + 1, 1);

    } else {
      this.notifyService.warning(SELECT_MOVE_COLUMN_MESSAGE);
    }
  }

  /** 上移 */
  moveUp() {
    if (this.hasCheckeds('r')) {
      const obj = this._getSelectColumnInfo();
      if (obj) {
        const len = obj.cols.length;
        const index = obj.index;
        if (index !== 0) {
          const tempArr = this.selectedColumns.splice(index, len);
          this.selectedColumns.splice(index - 1, 0, ...tempArr);
        }

      }
    } else {
      this.notifyService.warning(SELECT_MOVE_COLUMN_MESSAGE);
    }
  }

  /** 下移 */
  moveDown() {
    if (this.hasCheckeds('r')) {
      const obj = this._getSelectColumnInfo();
      if (obj) {
        const len = this.selectedColumns.length;
        const index = obj.index;
        if (index === 0 || index !== len - 1) {
          const tempArr = this.selectedColumns.splice(index, 1);
          this.selectedColumns.splice(index + 1, 0, ...tempArr);
        }

      }
    } else {
      this.notifyService.warning(SELECT_MOVE_COLUMN_MESSAGE);
    }
  }

  /** 置底 */
  moveBottom() {
    const obj = this._getSelectColumnInfo();
    if (obj) {
      this.selectedColumns.push(obj.cols[0]);
      this.selectedColumns.splice(obj.index, 1);
    } else {
      this.notifyService.warning(SELECT_MOVE_COLUMN_MESSAGE);
    }
  }

  //#endregion

  private convertTreeNodes2PlainObject(nodes: TreeNode[], r: any[] = []): TreeNode[] {
    if (nodes) {
      nodes.forEach(n => {
        r.push(n);
        if (n.children) {
          this.convertTreeNodes2PlainObject(n.children, r);
        }
      });
    }

    return r;
  }

  getTreeNodeByID(fieldId: string) {
    return this.plainColumns.find(column => column.data.id === fieldId);
  }
  /**
   * 确定
   */
  clickConfirm() {
    const dgViewModel = this.dgVMService.getDgViewModel(this.editorParams.viewModelId);
    const newFields = [];
    const newFieldIds = [];
    // 组装GridField数据
    this.selectedColumns.forEach(co => {
      delete co.inValidTip;
      delete co.isInValidBinding;
      let value = this.value.find(v => {
        if (v.binding && v.binding.field) {
          return v.binding.field === co.id;
        }
      });
      if (!value) {
        // 关联字段/UDT字段设置dataField
        const treeNode = this.sourceTree.findRowNode(co.id);
        const dataField = this._getDataField(treeNode, co.label);
        const fieldType = this.editorParams.gridType === DgControl.DataGrid.type ? DgControl.GridField.type : DgControl.TreeGridField.type;
        value = this.controlCreatorService.createGridFieldBySchemaFeild(co, dataField, this.fieldEditable,
          fieldType, this.editorParams.controlSource);

        dgViewModel.addField(co); // DgVM增加字段
      }
      newFields.push(value);
      newFieldIds.push(co.id);
    });

    // DgVM 删除字段
    const deletedFields = dgViewModel.fields.filter(f => !newFieldIds.includes(f.id));
    if (deletedFields && deletedFields.length > 0) {
      const deletedFieldIds = deletedFields.map(f => f.id);
      dgViewModel.removeField(deletedFieldIds);

      //  删除schema字段---零代码场景
      if (this.formBasicService.envType === DesignerEnvType.noCode) {
        this.schemaService.removeSchemaField(deletedFieldIds);
      }

      // 若字段配置了表达式，需要删除表达式
      if (this.domService.expressions && this.domService.expressions.length && deletedFieldIds.length) {
        this.domService.expressions = this.domService.expressions.filter(e => !deletedFieldIds.includes(e.fieldId));
      }
    }

    this.submitModal.emit({ value: newFields }); // 属性编辑器自动将newFields赋值给对应控件value
  }


  /**
   * 取消
   */
  clickCancel() {
    this.closeModal.emit();
  }


  private _getDataField(treeNode, label) {
    let dataField;
    if (treeNode.parent) {
      dataField = treeNode.parent.data.label + '.' + label;
      dataField = this._getDataField(treeNode.parent, dataField);
    } else {
      dataField = label;
    }
    return dataField;
  }


  onDrop({ removedIndex, addedIndex, payload }: DropResult) {
    let itemToAdd = payload;
    if (removedIndex !== null) {
      itemToAdd = this.selectedColumns.splice(removedIndex, 1)[0];
    }
    if (addedIndex !== null && itemToAdd) {
      this.selectedColumns.splice(addedIndex, 0, itemToAdd);
    }
  }

  getGhostParent() {
    return window.document.body;
  }

  getSourceTreeChildPayload(index: number) {
    return this.sourceTree.serializedValue[index].node.data;
  }

  private makeSourceTreeDraggable() {
    const tbodyList = this.sourceTree.el.nativeElement.getElementsByTagName('tbody');
    if (!tbodyList.length) {
      return;
    }
    const containerElement = tbodyList[0];
    const containerOptions: ContainerOptions = {
      behaviour: 'copy',
      getGhostParent: this.getGhostParent,
      groupName: 'selectColumn',
      nonDragAreaSelector: '[ng-reflect-select-row-disabled=true]',
      getChildPayload: this.getSourceTreeChildPayload.bind(this)
    };
    this['sourceTreeContainer'] = smoothDnD(containerElement, containerOptions);
    const children = containerElement.children;
    // for (let i = 0; i < children.length; i++) {
    //   children[i].classList.add(constants.wrapperClass);
    // }

    Array.prototype.forEach.call(children, (item: HTMLElement) => {
      item.classList.add(constants.wrapperClass);
    });
  }
}
